from django import forms
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
from django.conf import settings
from bug_manage import models
import random
from django_redis import get_redis_connection
from utils import encrypt
from bug_manage.forms.bootstrap import BootStrapForm
from utils.tencent.sms import send_sms_single
"""利用ModelForm可完成 html自动表单展示  和 表单校验"""
# 继承django自带的表单处理forms.ModelForm



class RegisterModelForm(BootStrapForm,forms.ModelForm):
    """
    注册表单自动生成
    """
    mobile_phone = forms.CharField(label='手机号码',
                                   validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', message='手机号码格式错误'), ])
    password = forms.CharField(label='密码', min_length=8, max_length=64,
                               error_messages={'min_length': "密码长度不能小于8个字符",
                                               'max_length': "密码长度不能超过64个字符"},
                               widget=forms.PasswordInput())
    confirm_password = forms.CharField(label='重复密码', min_length=8, max_length=64,
                               error_messages={'min_length': "重复密码长度不能小于8个字符",
                                               'max_length': "重复密码长度不能超过64个字符"},
                               widget=forms.PasswordInput())
    code = forms.CharField(label='验证码', widget=forms.TextInput())

    # 把那张表转化成form组件
    class Meta:
        # 这个意思即是把UserInfo转化成form组件
        model = models.UserInfo
        # 把表中的所有的字段都做转化，这里也可以传递一个list,可以指定显示某些字段,指定显示顺序
        fields = ['username', 'email', 'password', 'confirm_password', 'mobile_phone', 'code']
        # fields = "__all__"

    def clean_username(self):
        username = self.cleaned_data.get('username')
        exists = models.UserInfo.objects.filter(username=username).exists()
        if exists:
            raise ValidationError('用户已存在')
        return username

    def clean_email(self):
        email = self.cleaned_data.get('email')
        exists = models.UserInfo.objects.filter(email=email).exists()
        if exists:
            raise ValidationError('邮箱已存在')
        return email

    def clean_password(self):
        password = self.cleaned_data.get('password')
        #加密返回
        password = encrypt.md5(password)
        return password

    def clean_confirm_password(self):
        password = self.cleaned_data.get('password')
        confirm_password = self.cleaned_data.get('confirm_password')
        confirm_password = encrypt.md5(confirm_password) #md5加密
        if password != confirm_password:
            raise ValidationError('两次密码不一致')
        return confirm_password

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data.get('mobile_phone')
        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if exists:
            raise ValidationError('手机号已注册')
        return mobile_phone

    def clean_code(self):
        code = self.cleaned_data.get('code')
        mobile_phone = self.cleaned_data.get('mobile_phone')
        conn = get_redis_connection()
        try:
            redis_code = conn.get(mobile_phone)
            if not redis_code:
                raise ValidationError('验证码失效，请重新发送')
        except:
            raise ValidationError('请点击获取验证码')
        redis_code_str = redis_code.decode('utf-8')
        if code.strip() !=  redis_code_str:
            raise ValidationError("验证码错误,请重新输入")
        return code

class SendSmsForm(forms.Form):
    """
    发送短信
    """
    mobile_phone = forms.CharField(label='手机号码',
                                   validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$',  message='手机号码格式错误'), ])

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_mobile_phone(self):
        """手机号码校验的钩子"""
        mobile_phone = self.cleaned_data.get('mobile_phone')
        # print(mobile_phone)
        #判断手机号是否存在
        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        # 判断短信模板是否有问题
        tpl = self.request.GET.get('tpl')
        if tpl == 'login':
            if not exists:
                raise ValidationError('手机号码未注册')
        elif tpl == 'register':
            if exists:
                raise ValidationError('手机号码已注册')
        else:
            raise ValidationError('短信模板不存在')

        template_id = settings.TENCENT_SMS_TEMPLATES.get(tpl)
        print('tpl:%s'%tpl)
        print(template_id)
        if not template_id:
            raise ValidationError('短信模板错误')
        code = random.randrange(1000, 9999)
        # print('code:%s' % code)
        # 校验数据库中是否有该号码
        # 发短信 & 写redis
        if tpl == 'login':
            if not exists:
                raise ValidationError('手机号码不存在')
            sms = send_sms_single(mobile_phone, template_id, [code, 5])
        else:
            if exists:
                raise ValidationError('手机号码已存在')
            sms = send_sms_single(mobile_phone, template_id, [code, 5])

        if sms['result'] != 0:
            raise ValidationError('短信发送失败, {}'.format(sms['errmsg']))

        # 验证码写入redis(使用django-redis)
        conn = get_redis_connection("default")
        conn.set(mobile_phone, code, ex=60)
        return mobile_phone

class LoginSMSForm(BootStrapForm,forms.Form):
    mobile_phone = forms.CharField(label='手机号码',
                                   validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', message='手机号码格式错误'), ])
    code = forms.CharField(label='验证码', widget=forms.TextInput())

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data.get('mobile_phone')
        # 判断手机号是否存在
        user_object = models.UserInfo.objects.filter(mobile_phone=mobile_phone).first()
        if not user_object:
            raise ValidationError('手机号码未注册')
        return user_object

    def clean_code(self):
        code = self.cleaned_data.get('code')
        user_object = self.cleaned_data.get('mobile_phone')
        #如果获取不到用户，则无需校验
        if not user_object:
            return code
        conn = get_redis_connection()
        #处理redis中没有验证码的异常，既用户未获取验证码点击登录
        try:
            redis_code = conn.get(user_object.mobile_phone)
            if not redis_code:
                raise ValidationError('验证码失效，请重新发送')
        except:
            raise ValidationError('请点击获取验证码')
        redis_code_str = redis_code.decode('utf-8')
        if code.strip() != redis_code_str:
            raise ValidationError("验证码错误,请重新输入")
        return code

class LoginForm( BootStrapForm, forms.Form) :
    """登录表单"""
    username = forms.CharField(label='用户名/手机号/邮箱')
    password = forms.CharField(label='密码', widget=forms.PasswordInput(render_value=True))
    code = forms.CharField(label='图片验证码')

    def __init__(self, request, *args , **kwargs):
        super().__init__(*args,**kwargs)
        self.request = request


    def clean_password(self):
        password = self.cleaned_data.get('password')
        # 加密返回
        password = encrypt.md5(password)
        return password

    def clean_code(self):
        code = self.cleaned_data.get('code')
        #取session获取验证码
        session_code = self.request.session.get('image_code')
        if not session_code:
            raise ValidationError('验证码已过期，请重新获取')
        if code.strip().upper() != session_code.strip().upper():
            raise ValidationError('验证码输入错误')
        return code


